const compileUtil = {
    getVal(expr,vm){
        return expr.split('.').reduce((data,currentVal)=>{
            // console.log(currentVal)
            return data[currentVal];//调用变量的get()
        },vm.$data);
    },
    setVal(expr,vm,inputVal){
        return expr.split('.').reduce((data,currentVal)=>{
            // console.log(currentVal)
            data[currentVal] = inputVal;
        },vm.$data);
    },
    getContentVal(expr,vm){//只替换{{}}中的内容
        return expr.replace(/\{\{(.+?)\}\}/g,(...args)=>{
            
            return this.getVal(args[1],vm)
        })
    },
    text(node, expr, vm) { //expr：msg
        let value;
        if(expr.indexOf('{{') !== -1){
            value = expr.replace(/\{\{(.+?)\}\}/g,(...args)=>{
                new Watcher(vm,args[1],(newVal)=>{
                    //绑定观察者，将来数据变化触发这里的回调 进行更新
                    this.updater.textUpdater(node, this.getContentVal(expr,vm))
                })
                return this.getVal(args[1],vm)
            })
        }else{
            value = this.getVal(expr,vm);
        }
        
        
        this.updater.textUpdater(node, value)
    },
    html(node, expr, vm) {
        const value = this.getVal(expr,vm);
        new Watcher(vm,expr,(newVal)=>{
            this.updater.htmlUpdater(node, newVal)
        })
        this.updater.htmlUpdater(node, value)
    },
    model(node, expr, vm) {
        const value = this.getVal(expr,vm);
        //绑定更新函数 数据=》视图
        new Watcher(vm,expr,(newVal)=>{
            this.updater.modelUpdater(node, newVal)
        })
        //视图=》数据=》视图
        node.addEventListener('input',(e)=>{
            //设置值
            this.setVal(expr,vm,e.target.value)
        })
        this.updater.modelUpdater(node, value)
    },
    on(node, expr, vm, eventName) {
        let fn = vm.$options.methods && vm.$options.methods[expr];
        node.addEventListener(eventName,fn.bind(vm),false)
    },
    updater: {
        textUpdater(node, value) {
            console.log(node.textContent,value)
            node.textContent = value
        },
        htmlUpdater(node, value){
            node.innerHTML = value
        },
        modelUpdater(node, value){
            node.value=value
        }
    }
}
class Compile {
    constructor(el, vm) {
        this.el = this.isElementNode(el) ? el : document.querySelector(el);
        this.vm = vm;
        //获取文档碎片对象 放入内存中减少回流重绘
        const fragment = this.node2Fragment(this.el)
        this.compile(fragment)
        //追加到跟元素
        this.el.appendChild(fragment)
    }
    compile(fragment) {
        const childNodes = fragment.childNodes;
        [...childNodes].forEach(child => {
            if (this.isElementNode(child)) {
                //是元素节点
                // console.log('元素节点', child)
                this.compileElement(child)
            } else {
                //是文本节点
                // console.log('文本节点', child)
                this.compileText(child)
            }
            if (child.childNodes && child.childNodes.length) {
                this.compile(child);
            }
        })
    }
    compileElement(node) {

        const attributes = node.attributes;
        // console.log(attributes)
        let a = [...attributes].forEach(attr => {
            // console.log(attr)
            const {
                name,
                value
            } = attr;
            // console.log(name, value)
            if (this.isDirective(name)) {//v-
                const [, dirctive] = name.split('-');
                const [dirName, eventName] = dirctive.split(':');
                console.log(dirctive, dirName, eventName)
                //更新数据 数据驱动视图
                compileUtil[dirName](node, value, this.vm, eventName)
                //删除有指令的标签上的属性
                node.removeAttribute('v-'+dirctive)

            }else if(this.isEventName(name)){
                const [, eventName] = name.split('@');
                compileUtil.on(node,value,this.vm,eventName)
            }
        });
    }
    compileText(node) {
        // console.log(node)
        const content = node.textContent;
        if(/\{\{(.+?)\}\}/.test(content)){
            // console.log(content)
            compileUtil.text(node,content,this.vm)
        }
    }
    isDirective(attrName) {
        return attrName.startsWith('v-')
    }
    isEventName(attrName) {
        return attrName.startsWith('@')
    }
    node2Fragment(el) {
        //创建文档碎片
        const f = document.createDocumentFragment();
        let firstChild;
        while (firstChild = el.firstChild) {
            f.appendChild(firstChild);
        }
        return f;
    }

    isElementNode(node) {
        return node.nodeType === 1;
    }


}
class MVue {
    constructor(options) {
        this.$el = options.el;
        this.$data = options.data;
        this.$options = options;
        if (this.$el) {
            //实现一个数据观察者
            new Observer(this.$data)
            //实现一个指令解析器
            new Compile(this.$el, this)
            this.proxyData(this.$data)//数据代理
        }

        
    }
    proxyData(data){
        for(const key in data){
            Object.defineProperty(this,key,{
                get(){
                    return data[key]
                },
                set(newVal){
                    console.log('proxyData:',newVal)
                    data[key] = newVal
                }
            })
        }
        
    }
}